/*
 * Copyright (c) 2015, FPX and/or its affiliates. All rights reserved.
 * Use, Copy is subject to authorized license.
 */
package com.fpx.open.platform.common.util;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;

import com.fpx.open.platform.common.ConfigInfo;
import com.fpx.open.platform.common.constant.AppConstant;
import com.fpx.open.platform.common.constant.MessageConstant;
import com.fpx.open.platform.common.constant.SysConstant;
import com.fpx.open.platform.domain.ae.AEOrder;
import com.fpx.open.platform.domain.ae.ContactPerson;
import com.fpx.open.platform.domain.ae.Item;
import com.fpx.open.platform.domain.ae.Order;
import com.fpx.open.platform.domain.ae.SubOrder;
import com.fpx.open.platform.domain.ae.batch_send.BatchSendEvent;
import com.fpx.open.platform.domain.ae.batch_send.BatchSendEventBody;
import com.fpx.open.platform.domain.ae.batch_send.BatchSendEventsRequest;
import com.fpx.open.platform.domain.ae.batch_send.Product;
import com.fpx.open.platform.domain.ae.cancel.CancelEventsRequest;
import com.fpx.open.platform.domain.ae.send.SendEventsRequest;
import com.fpx.open.platform.domain.prealert.BatchArrivalPrealertTR;
import com.fpx.open.platform.domain.prealert.CountryMapping;
import com.fpx.open.platform.domain.prealert.DeclareInvoiceInfo;
import com.fpx.open.platform.domain.prealert.MailCargoTypeMapping;
import com.fpx.open.platform.domain.prealert.OrderHandover;
import com.fpx.open.platform.domain.prealert.OrderInfo;
import com.fpx.open.platform.domain.prealert.OrderPrintData;
import com.fpx.open.platform.domain.prealert.PrealertDeclareInvoiceAttachTR;
import com.fpx.open.platform.domain.prealert.PrealertDeclareInvoiceTR;
import com.fpx.open.platform.domain.prealert.PrealertOrderAttachTR;
import com.fpx.open.platform.domain.prealert.PrealertOrderTR;
import com.fpx.open.platform.domain.prealert.PrealertShipperConsigneeTR;
import com.fpx.open.platform.domain.prealert.ProductMapping;
import com.fpx.open.platform.domain.prealert.Refunder;

/**
 * AE订单工具类
 * @author shiwei
 * @date 2015年7月5日
 */
public class AEOrderUtil {
	
	
	/**
	 * 转换AE发送的请求报文为订单对象
	 * @param eventRequest
	 * @return
	 */
	public static OrderInfo convertSendRequest(BatchSendEventsRequest eventRequest, ConfigInfo configInfo){
		BatchSendEvent batchSendEvent = eventRequest.getLogisticsEvent();
		OrderInfo orderInfo = new OrderInfo();
		
		BatchSendEventBody body = batchSendEvent.getEventBody();
		orderInfo.setShipperConsignee(convertShipperConsignee(body));
		
		PrealertOrderTR prealertOrder = convertPrealertOrder(configInfo, body);
        orderInfo.setPrealertOrder(prealertOrder);
        prealertOrder.setPk_code(batchSendEvent.getEventHeader().getEventTarget());
        
        PrealertOrderAttachTR orderAttach = convertPrealertOrderAttach(body);
        orderAttach.setCo_warehousecode("FPXSS");
        orderInfo.setOrderAttach(orderAttach);
        
        List<DeclareInvoiceInfo> declareInvoiceList = convertDeclareInvoice(body, prealertOrder);
        orderInfo.setDeclareInvoices(declareInvoiceList);
		return orderInfo;
	}


	/**
	 * 转换申报信息
	 * @param body
	 * @return
	 */
	private static List<DeclareInvoiceInfo> convertDeclareInvoice(BatchSendEventBody body, PrealertOrderTR prealertOrder) {
		List<DeclareInvoiceInfo> declareInvoiceList = new ArrayList<DeclareInvoiceInfo>();
        List<Product> productList = body.getOrderInfos();
        DeclareInvoiceInfo declareInvoiceInfo = null;
        PrealertDeclareInvoiceTR prealertDeclareInvoice = null;
        PrealertDeclareInvoiceAttachTR prealertDeclareInvoiceAttach = null;
        int i = 1;
        int totalQuantity = 0;
        for(Iterator<Product> iter = productList.iterator(); iter.hasNext(); i++){
        	Product product = iter.next();
        	declareInvoiceInfo = new DeclareInvoiceInfo();
        	prealertDeclareInvoice = new PrealertDeclareInvoiceTR();
        	prealertDeclareInvoiceAttach = new PrealertDeclareInvoiceAttachTR();
        	
        	prealertDeclareInvoice.setDi_ename(product.getProductNameEN());
        	prealertDeclareInvoice.setDi_cname(product.getProductNameCN());
        	Integer quantity = product.getProductQantity();
        	String totalPrice = AEOrderUtil.convertMoney(product.getProductPrice());
        	Double unitPrice = Double.parseDouble(totalPrice) / quantity;
        	prealertDeclareInvoice.setDi_unitprice(unitPrice.toString());
        	prealertDeclareInvoice.setDi_pcs(quantity.toString());
        	prealertDeclareInvoice.setDi_weight(AEOrderUtil.convertWeight(product.getProductWeight()));
        	prealertDeclareInvoice.setDi_id(String.valueOf(i));
        	prealertDeclareInvoice.setDi_totalprice(totalPrice);
        	totalQuantity += quantity;
        	
        	prealertDeclareInvoiceAttach.setDi_itemcategorycname(product.getProductCateCN());
        	prealertDeclareInvoiceAttach.setDi_itemcategoryname(product.getProductCateEN());
        	prealertDeclareInvoiceAttach.setDi_id(String.valueOf(i));
        	prealertDeclareInvoiceAttach.setDi_itemid(product.getProductId());
        	
        	declareInvoiceInfo.setDeclareInvoice(prealertDeclareInvoice);
        	declareInvoiceInfo.setDeclareInvoiceAttach(prealertDeclareInvoiceAttach);
        	declareInvoiceList.add(declareInvoiceInfo);
        }
        prealertOrder.setCo_pieces(String.valueOf(totalQuantity));
		return declareInvoiceList;
	}


	/**
	 * 转换订单附属信息
	 * @param body
	 * @return
	 */
	private static PrealertOrderAttachTR convertPrealertOrderAttach(BatchSendEventBody body) {
		PrealertOrderAttachTR orderAttach = new PrealertOrderAttachTR();
        orderAttach.setCo_note(body.getRemark());
        orderAttach.setCo_customerweight(AEOrderUtil.convertWeight(body.getTotleweight()));
        orderAttach.setCo_transactionid(body.getTradeId());
        if(body.getItotlevalue() != null){
        	orderAttach.setCo_declarevalue(AEOrderUtil.convertWeight(body.getItotlevalue()));
        }
		return orderAttach;
	}


	/**
	 * 转换订单主体信息
	 * @param configInfo
	 * @param body
	 * @return
	 */
	private static PrealertOrderTR convertPrealertOrder(ConfigInfo configInfo, BatchSendEventBody body) {
		PrealertOrderTR prealertOrder = new PrealertOrderTR();
		prealertOrder.setCo_servehawbcode(body.getMailNo());
        prealertOrder.setMct_code(body.getMailKind());

        prealertOrder.setOs_code("P");// 订单状态代码.P表示预报状态
        prealertOrder.setDs_code("A");// 数据来源，例如传统物流、订单宝等
        prealertOrder.setPit_code("A");// 数据对接类型代码，例如网站上传、离线预报上传、API对接、仓储写入等
        prealertOrder.setCm_id(configInfo.getAeCustomerID());// 客户ID
        prealertOrder.setCm_id_platform(configInfo.getAeCustomerID());// 商务平台ID
        prealertOrder.setCo_orderno(body.getOrderCode());// 客户订单号码，一般由客户自己填写，同客户内具有唯一性。不同客户间可能出现重复
        prealertOrder.setPm_code("P");// 付款方式代码。P为预付
        prealertOrder.setIs_code("N");// 保险状态，例如申请、审核通过等。统一作未买保险处理
        prealertOrder.setCo_odachecksign("N");// ODA校验标志。Y表示已经校验过，N表示尚未校验
        prealertOrder.setCo_odasign("U");// ODA标志。Y表示为ODA，N表示非ODA，U表示未知
        prealertOrder.setCo_holdsign("N");// 拦截标志。Y表示发件人要求拦截，N表示放行
        // prealertOrder.setCo_insurancevalue("0");// 发件人指定的保险金额，默认为形式发票金额。若不买保险则为空
        // prealertOrder.setEo_buyerid("8888");// 买家ID
        // prealertOrder.setBs_id("");//运单业务ID，收货后写入
        prealertOrder.setCp_id_creat(configInfo.getAeCustomerID());// 创建订单的联系人
        prealertOrder.setCo_createdate(DateUtil.getCurrTime(DateUtil.DATE_FORMAT_S));// 订单创建日期
        prealertOrder.setCo_modifydate(DateUtil.getCurrTime(DateUtil.DATE_FORMAT_S));// 订单最后修改日期
        prealertOrder.setCo_postdate(DateUtil.getCurrTime(DateUtil.DATE_FORMAT_S));// 订单提交日期
        prealertOrder.setPackage_code(body.getPackageCode());
        prealertOrder.setArrival_mode(SysConstant.ArrivalMode.GOT);
        if(body.getHasBattery()){
        	prealertOrder.setCo_battery("Y");
        }else{
        	prealertOrder.setCo_battery("N");
        }
        // 发件人退回标志。当中转异常后，Y表示发件人要求退回，N表示无须退回。
        Integer undeliveryOption = body.getUndeliveryOption();
        if (undeliveryOption != null && 2 == undeliveryOption) {
            prealertOrder.setCo_returnsign("Y");
        } else {
            prealertOrder.setCo_returnsign("N");
        }
        prealertOrder.setCo_returnedsign("N");
		return prealertOrder;
	}

	
	/**
	 * 转换收发件人信息
	 * @param body
	 */
	private static PrealertShipperConsigneeTR convertShipperConsignee(BatchSendEventBody body) {
		PrealertShipperConsigneeTR shipperConsignee = new PrealertShipperConsigneeTR();
		String consigneeCountry = body.getRcountry();
		if (consigneeCountry != null) {
			shipperConsignee.setSc_consigneecountry(consigneeCountry);
        } else {
        	shipperConsignee.setSc_consigneecountry("CN");
        	shipperConsignee.setSc_consigneeaddress1(consigneeCountry);
        }
		shipperConsignee.setSc_consigneestreet(body.getRaddress());
		shipperConsignee.setSc_consigneecity(body.getRcity());
		shipperConsignee.setSc_consigneecountry(body.getRcountry());
		shipperConsignee.setSc_consigneeemail(body.getRemail());
		shipperConsignee.setSc_consigneename(body.getRname());
		shipperConsignee.setSc_consigneetelephone(body.getRphone());
		shipperConsignee.setSc_consigneepostcode(body.getRpostcode());
		shipperConsignee.setSc_consigneeprovince(body.getRprovince());
		
		// 要判断字节长度为2,避免中文引起长度超出的问题 modify by dranson on 2013-12-05
		String shipperCountry = body.getCountry(); 
        if (StringUtils.isNotBlank(shipperCountry) && shipperCountry.getBytes().length == 2) {
        	shipperConsignee.setSc_shippercountry(shipperCountry.toUpperCase());
        } else {
            // 因目前速卖通传过来国家与4px标注国家二字码无法匹配，暂时hardcode保证测试,address1记录速卖通传入国家
        	shipperConsignee.setSc_shippercountry("CN");
        	shipperConsignee.setSc_shipperaddress1(shipperCountry);
        }
        shipperConsignee.setSc_shipperstreet(body.getSaddress());
        shipperConsignee.setSc_shippercity(body.getScity());
        shipperConsignee.setSc_shippername(body.getSname());
        shipperConsignee.setSc_shippertelephone(body.getSphone());
        shipperConsignee.setSc_shipperpostcode(body.getSpostcode());
        shipperConsignee.setSc_shipperprovince(body.getSprovince());
		shipperConsignee.setSc_shipperwangwangid(body.getSwangwangId());
		
		return shipperConsignee;
	}
	
	
	/**
	 * 整理收发件人地址 
	 * @param shipperConsignee
	 */
	public static void putShipperConsigneeAddr(PrealertShipperConsigneeTR shipperConsignee) {
		String shipperAddress1 = processShipperStreet(shipperConsignee.getSc_shipperstreet(),
                shipperConsignee.getSc_shipperprovince(), shipperConsignee.getSc_shippercity());
        shipperConsignee.setSc_shipperaddress1(shipperAddress1);
        // 中国先省后城市
        shipperConsignee.setSc_shipperaddress2(shipperConsignee.getSc_shipperprovince() + "  "
                + shipperConsignee.getSc_shippercity());
        shipperConsignee.setSc_shipperaddress3(shipperConsignee.getSc_shipperpostcode() + "  "
                + shipperConsignee.getSc_shippercountry());

        // 补充收件人的地址一、二、三信息以满足打印标签需要
        String consigneeAddress1 = processConsigneeStreet(shipperConsignee.getSc_consigneestreet(),
                shipperConsignee.getSc_consigneeprovince(), shipperConsignee.getSc_consigneecity());
        shipperConsignee.setSc_consigneeaddress1(consigneeAddress1);
        // 外国先城市后省
        shipperConsignee.setSc_consigneeaddress2(shipperConsignee.getSc_consigneecity() + "  "
                + shipperConsignee.getSc_consigneeprovince());
        shipperConsignee.setSc_consigneeaddress3(shipperConsignee.getSc_consigneepostcode() + "  "
                + shipperConsignee.getSc_consigneecountry());
	}
	
    /**
     * 处理发件人地址 ,速卖通传入地址格式：GuangDong^^^ShenZhen^^^LongGang^^^bantian street yangma community qinghua flats 1208
     * @param street
     * @param province
     * @param city
     * @return
     */
    public static String processShipperStreet(String street, String province, String city) {
        // 先去除省、市
        String address = processConsigneeStreet(street, province, city);
        if (address != null) {
            address = address.replace("^", " ");
            return address.trim();
        }
        return null;
    }

    /**
     * 处理收件人地址(去除省市)，速卖通传入地址格式为:省+城市+“other”+street
     * @param street
     * @param province
     * @param city
     * @return
     */
    private static String processConsigneeStreet(String street, String province, String city) {
        if (street != null) {
            // 针对特殊字符会导致异常，先处理掉 modify by dranson on 2013-12-12
            String[] ary = { "\\", "+", "*", "^", "|", "{", "[", "(", ")", "$", "?" };
            if (province != null) {
                for (String s : ary) {
                    province = province.replace(s, "\\" + s);
                }
                if(street.contains("^^^")){
                	street = street.replaceFirst(province, "");
                }
            }
            if (city != null) {
                for (String s : ary) {
                    city = city.replace(s, "\\" + s);
                }
                if(street.contains("^^^")){
                	street = street.replaceFirst(city, "");
                }
            }
            return street.replaceFirst("other", "");
        }
        return null;
    }
    
    
    /**
	 * 转换订单交接信息
	 * @param eventRequest
	 * @return
	 */
	public static OrderHandover convertToOrderHandover(BatchSendEventsRequest eventRequest) {
		OrderHandover orderHandover = new OrderHandover();
		BatchSendEventBody body = eventRequest.getLogisticsEvent().getEventBody();
		String packageCode = body.getPackageCode();
		if(StringUtils.isNotBlank(packageCode) && !StringUtils.equals("CN_PACKAGE_CODE_ABS", packageCode)){
			orderHandover.setPackageWeight(Double.parseDouble(convertWeight(body.getPackageWeight())));
			orderHandover.setOrdersInPackage(body.getOrdersInPackage().intValue());
		}
		orderHandover.setBatchNo(body.getBatchNo());
		orderHandover.setPackageCode(body.getPackageCode());
		orderHandover.setSource(OrderHandover.SOURCE_ALI);
		return orderHandover;
	}
	
	
    /**
     * 将克转换为千克
     * @param weight
     * @return
     */
    public static String convertWeight(Long weight) {
        String weightStr = null;
        if (weight != null) {
            float rate = 1000;
            Float weight1 = weight / rate;
            return weight1.toString();
        }
        return weightStr;
    }


    /**
     * 将美分转换为美元
     * @param money
     * @return
     */
    public static String convertMoney(Long money) {
        String moneyStr = null;
        if (money != null) {
            double rate = 100;
            Double rmbMoney = money / rate;
            return rmbMoney.toString();
        }
        return moneyStr;
    }
    
    public static String longToString(Long value) {
        if (value != null) {
            return String.valueOf(value);
        }
        return null;
    }
    
    public static AEOrder convertSendRequest(SendEventsRequest eventRequest, ConfigInfo configInfo) {
        AEOrder aeOrder = new AEOrder();
        Order order = eventRequest.getLogisticsEvent().getEventBody().getOrder();
        boolean isEDI = false;
        String extendFields = order.getExtendFields();
        String ediValue = AEOrderUtil.getExtendFieldsValue(extendFields, "EDI");
        if(StringUtils.equals(ediValue, Boolean.TRUE.toString())){
        	isEDI = true;
        }
        String lazadaNo = AEOrderUtil.getExtendFieldsValue(extendFields, "fmtn");
        List<SubOrder> subOrders = order.getSubOrders();
        BatchArrivalPrealertTR batchPrealert = new BatchArrivalPrealertTR();
        batchPrealert.setBap_labelcode(order.getMailNo());
        batchPrealert.setBap_referenceno(order.getOrderCode());
        batchPrealert.setBap_shipperremark(order.getRemark());
        batchPrealert.setBap_expressid(longToString(order.getDomesticExpressId()));
        batchPrealert.setBap_remark(order.getDomesticExpressCode() + "::" + order.getDomesticExpressName());
        batchPrealert.setBap_doorPickup(order.getDoorPickup());
        batchPrealert.setService_item_id(order.getServiceItemId());
        batchPrealert.setBizCode(order.getBizCode());
        // FIXME 联系人JSON后存储？
        if(order.getPickupContact() != null){
        	batchPrealert.setPickuperContact(order.getPickupContact());
        }
        
        if(order.getSendContact() != null){
            batchPrealert.setBap_sender(JsonBinder.buildNonDefaultBinder().toJson(order.getSendContact()));
        }
        if (order.getReceiverContact() != null) {
            batchPrealert.setReceiver(order.getReceiverContact());
            batchPrealert.setBap_receiver(JsonBinder.buildNonDefaultBinder().toJson(order.getReceiverContact()));
        }

        batchPrealert.setPit_code("A");// 数据对接类型代码，例如网站上传、离线预报上传、API对接、仓储写入等
        batchPrealert.setBps_code("S");// 批次操作状态，例如开始(S:start)、完成(C;complete)、删除(D;discart)
        // 货物交接方式，AD(Agent delivery):货代提货,EC(Express Collect):快递到货,CD(Customer delivery):现场收货 ,DP(Door Transfer):上门提货
        batchPrealert.setUm_code("EC");
        batchPrealert.setCm_id_shipper(configInfo.getAeCustomerID());// 客户ID，是客户的唯一识别
        batchPrealert.setCm_id_platform(configInfo.getAeCustomerID());// 商务平台ID
        batchPrealert.setBap_estimatedatepickup(DateUtil.getCurrTime(DateUtil.DATE_FORMAT_S));// 预期提货/发出时间??
        batchPrealert.setBap_actualarrivaldate(DateUtil.getCurrTime(DateUtil.DATE_FORMAT_S));// 实际到货日期??

        // batchPrealert.setBap_weight(strBap_weight);
        batchPrealert.setBap_createdate(DateUtil.getCurrTime(DateUtil.DATE_FORMAT_S));
        batchPrealert.setCp_id_modify(configInfo.getAeCustomerID());// 创建的联系人
        batchPrealert.setCp_id_creat(configInfo.getAeCustomerID());// 修改的联系人
        batchPrealert.setBap_modifydate(DateUtil.getCurrTime(DateUtil.DATE_FORMAT_S));
        batchPrealert.setCategory_feature(order.getCategoryFeature());
        
        String cloudPrintData = order.getCloudPrintData();
        if(cloudPrintData != null){
        	OrderPrintData orderPrintData = new OrderPrintData();
            orderPrintData.setData(cloudPrintData);
            aeOrder.setOrderPrintData(orderPrintData);
        } 
        
        Long totalPieces = 0L;
        List<OrderInfo> orderInfos = new ArrayList<OrderInfo>();
        if (subOrders != null) {
            batchPrealert.setBap_packages(String.valueOf(subOrders.size()));
            for (SubOrder subOrder : subOrders) {
            	batchPrealert.setSender(subOrder.getSendContact());
                OrderInfo orderInfo = new OrderInfo();

                PrealertOrderTR prealertOrder = new PrealertOrderTR();
                PrealertOrderAttachTR orderAttach = new PrealertOrderAttachTR();
                prealertOrder.setCo_servehawbcode(subOrder.getMailNo());
                prealertOrder.setPk_code(subOrder.getInterCarrier());
                prealertOrder.setMct_code(subOrder.getMailType());
                prealertOrder.setEDI(isEDI);
                prealertOrder.setOs_code("P");// 订单状态代码.P表示预报状态
                prealertOrder.setDs_code("A");// 数据来源，例如传统物流、订单宝等
                prealertOrder.setPit_code("A");// 数据对接类型代码，例如网站上传、离线预报上传、API对接、仓储写入等
                prealertOrder.setCm_id(configInfo.getAeCustomerID());// 客户ID
                prealertOrder.setCm_id_platform(configInfo.getAeCustomerID());// 商务平台ID
                // prealertOrder.setSc_id("strSc_id");//发件渠道，一般为某客户的分公司或直客下的业务员
                prealertOrder.setCo_orderno(subOrder.getOrderCode());// 客户订单号码，一般由客户自己填写，同客户内具有唯一性。不同客户间可能出现重复
                // prealertOrder.setCt_code_cargo("A");// 货物类型代码
                prealertOrder.setPm_code("P");// 付款方式代码。P为预付
                prealertOrder.setIs_code("N");// 保险状态，例如申请、审核通过等。统一作未买保险处理
                prealertOrder.setCo_odachecksign("N");// ODA校验标志。Y表示已经校验过，N表示尚未校验
                prealertOrder.setCo_odasign("U");// ODA标志。Y表示为ODA，N表示非ODA，U表示未知
                prealertOrder.setCo_holdsign("N");// 拦截标志。Y表示发件人要求拦截，N表示放行
                if(order.getCategoryFeature() != null && (order.getCategoryFeature().contains("02") || order.getCategoryFeature().contains("03"))){
                	// 品类包含了02： 带电 03：纯电，表示该货物带电
                	prealertOrder.setCo_battery("Y");
                }else{
                	prealertOrder.setCo_battery("N");
                }
                prealertOrder.setCp_id_creat(configInfo.getAeCustomerID());// 创建订单的联系人
                prealertOrder.setCo_createdate(DateUtil.getCurrTime(DateUtil.DATE_FORMAT_S));// 订单创建日期
                prealertOrder.setCo_modifydate(DateUtil.getCurrTime(DateUtil.DATE_FORMAT_S));// 订单最后修改日期
                prealertOrder.setCo_postdate(DateUtil.getCurrTime(DateUtil.DATE_FORMAT_S));// 订单提交日期
                
                int arrival_mode = SysConstant.ArrivalMode.SIGN;
                if(batchPrealert.isPickup()){
                	arrival_mode = SysConstant.ArrivalMode.PICKUP;
                }
                prealertOrder.setArrival_mode(arrival_mode);
                
                String systemOrderNo = prealertOrder.getCo_servehawbcode();
                if(StringUtils.isNotBlank(lazadaNo) && !StringUtils.equals(lazadaNo, "null")){
                	systemOrderNo = lazadaNo;
                }
                prealertOrder.setSystem_order_no(systemOrderNo);
                
                // 发件人退回标志。当中转异常后，Y表示发件人要求退回，N表示无须退回。
                String undeliveryOption = subOrder.getUndeliveryOption();
            	if(StringUtils.equals(undeliveryOption, "2")){
            		prealertOrder.setCo_returnsign("Y");
					ContactPerson refunderContact = order.getRefunderContact();
					if(refunderContact != null){
						Refunder refunder = new Refunder();
						BeanUtils.copyProperties(refunderContact, refunder);
						aeOrder.setRefunder(refunder);
					}
            	}else if(StringUtils.equals(undeliveryOption, "1")){
            		prealertOrder.setCo_returnsign("N");
            	}else{
            		prealertOrder.setCo_returnsign("I");
            	} 
                prealertOrder.setCo_returnedsign("N");// 已退回标志。Y表示货物已经退回发件人，N表示未退回。
                boolean isFirstRoute = Boolean.parseBoolean(subOrder.getFirstRoute());
                String route_count = "1";
                if(!isFirstRoute){
                	route_count = "2";
                }
                prealertOrder.setRoute_count(route_count);
                prealertOrder.setBiz_code(order.getBizCode());
                orderAttach.setCo_transactionid(subOrder.getTradeId());
                orderAttach.setCo_declarevalue(AEOrderUtil.convertMoney(subOrder.getTotalItemPrice()));
                orderAttach.setCo_customerweight(AEOrderUtil.convertWeight(subOrder.getWeight()));
                orderAttach.setCo_customerweightlimit(AEOrderUtil.convertWeight(subOrder.getWeightLimit()));
                orderAttach.setCo_note(subOrder.getRemark());
                orderAttach.setZone_code(subOrder.getZoneCode());
                Integer parcelInspect = order.getParcelInspect();
                if(parcelInspect != null){
                	orderAttach.setCo_parcelinspect(parcelInspect.toString());
                }

                PrealertShipperConsigneeTR shipperConsignee = convertContactPerson(null, subOrder.getSendContact(), "shipper");
                shipperConsignee = convertContactPerson(shipperConsignee, subOrder.getReceiverContact(), "consignee");

                orderInfo.setShipperConsignee(shipperConsignee);
                orderInfo.setOrderAttach(orderAttach);

                List<Item> items = subOrder.getItems();
                List<DeclareInvoiceInfo> declareInvoices = new ArrayList<DeclareInvoiceInfo>();
                Long co_pieces = 0L;
                if (items != null) {
                    for (int i = 0; i < items.size(); i++) {
                        Item item = items.get(i);
                        // 货物件数是取ItemQuantity的值，不是item项的数量 modify by dranson on 2013-11-15
                        co_pieces += item.getItemQuantity();
                        DeclareInvoiceInfo declareInvoiceInfo = new DeclareInvoiceInfo();
                        PrealertDeclareInvoiceTR declareInvoice = new PrealertDeclareInvoiceTR();
                        PrealertDeclareInvoiceAttachTR declareInvoiceAttach = new PrealertDeclareInvoiceAttachTR();
                        int di_id = i + 1;
                        declareInvoice.setDi_id(String.valueOf(di_id));
                        declareInvoiceAttach.setDi_itemid(item.getItemId());
                        declareInvoiceAttach.setDi_id(String.valueOf(di_id));
                        declareInvoice.setDi_name(item.getItemNameCN());
                        declareInvoice.setDi_ename(item.getItemName());
                        
                        // 扩展字段海关编码处理
                        declareInvoice.setDi_hscode(getExtendFieldsValue(item.getExtendFields()));
                        declareInvoice.setDi_cname(item.getItemNameCN());
                        declareInvoiceAttach.setDi_itemcategoryname(item.getItemCategoryName());
                        declareInvoiceAttach.setDi_itemcategorycname(item.getItemCategoryNameCN());
                        String hasBattery = "N";
                        if(item.isHasBattery()){
                        	hasBattery = "Y";
                        }
                        declareInvoiceAttach.setDi_has_battery(hasBattery);
                        declareInvoiceAttach.setDi_battery_info(item.getBatteryInfo());
                        
                        // 阿里传的是总价，计算出最小单价
                        String value = AEOrderUtil.convertMoney(item.getItemUnitPrice());
                        declareInvoice.setDi_totalprice(value);
                        Long quantity = item.getItemQuantity();
                        if(quantity != null && quantity > 0){
                        	Double unitPrice =  (Double.parseDouble(value) / quantity);
                        	declareInvoice.setDi_unitprice(unitPrice.toString());
                        }else{
                        	declareInvoice.setDi_unitprice(value);
                        }
                        declareInvoice.setDi_pcs(longToString(item.getItemQuantity()));
                        declareInvoice.setDi_weight(AEOrderUtil.convertWeight(item.getItemWeight()));
                        declareInvoice.setDi_url(item.getItemUrl());
                        declareInvoiceInfo.setDeclareInvoice(declareInvoice);
                        declareInvoiceInfo.setDeclareInvoiceAttach(declareInvoiceAttach);
                        declareInvoices.add(declareInvoiceInfo);
                    }
                }
                // 默认货物件数为1
                if (co_pieces == 0L) {
                    co_pieces = 1L;
                }
                // 大包裹的货物件数等于每个订单货物件数之和
                totalPieces += co_pieces;
                prealertOrder.setCo_pieces(co_pieces.toString());
                orderInfo.setPrealertOrder(prealertOrder);
                orderInfo.setDeclareInvoices(declareInvoices);
                orderInfos.add(orderInfo);
            }
        }
        batchPrealert.setBap_pieces(String.valueOf(totalPieces));
        aeOrder.setBatchPrealert(batchPrealert);
        aeOrder.setOrderInfos(orderInfos);
        return aeOrder;
    }
    
    
    private static PrealertShipperConsigneeTR convertContactPerson(PrealertShipperConsigneeTR originalPerson, ContactPerson person, String type) {

        if (person != null) {
            if (originalPerson == null) {
                originalPerson = new PrealertShipperConsigneeTR();
            }
            if ("shipper".equals(type)) {
                originalPerson.setSc_shipperwangwangid(person.getWangwangId());
                originalPerson.setSc_shippername(person.getName());
                String telephone = getTelephone(person);
                originalPerson.setSc_shippertelephone(telephone);
                originalPerson.setSc_shipperemail(person.getEmail());
                originalPerson.setSc_shipperidentifycode(person.getIdenCode());
                // 要判断字节长度为2,避免中文引起长度超出的问题 modify by dranson on 2013-12-05
                if (person.getCountry() != null && person.getCountry().getBytes().length == 2) {
                    originalPerson.setSc_shippercountry(person.getCountry().toUpperCase());
                } else {
                    // FIXME 因目前速卖通传过来国家与4px标注国家二字码无法匹配，暂时hardcode保证测试,address1记录速卖通传入国家
                    originalPerson.setSc_shippercountry("CN");
                    originalPerson.setSc_shipperaddress1(person.getCountry());
                }
                originalPerson.setSc_shipperprovince(person.getProvince());
                originalPerson.setSc_shippercity(person.getCity());
                originalPerson.setSc_shipperstreet(person.getStreetAddress());
                // XMS-5991 BUG修复，取消SC_ShipperAreaCode这个字段的插入 modify by dranson on 2014-01-03
                // originalPerson.setSc_shipperareacode(person.getAreaId());
                originalPerson.setSc_shipperpostcode(person.getZipCode());
            } else {
                originalPerson.setSc_consigneewangwangid(person.getWangwangId());
                originalPerson.setSc_consigneename(person.getName());
                String telephone = getTelephone(person);
                originalPerson.setSc_consigneetelephone(telephone);
                originalPerson.setSc_consigneeemail(person.getEmail());
                originalPerson.setSc_consigneeidentifycode(person.getIdenCode());
                if (person.getCountry() != null) {
                    originalPerson.setSc_consigneecountry(person.getCountry().toUpperCase());
                } else {
                    // FIXME 因目前速卖通传过来国家与4px标注国家二字码无法匹配，暂时hardcode保证测试,address1记录速卖通传入国家
                    originalPerson.setSc_consigneecountry("CN");
                    originalPerson.setSc_consigneeaddress1(person.getCountry());
                }
                originalPerson.setSc_consigneeprovince(person.getProvince());
                originalPerson.setSc_consigneecity(person.getCity());
                originalPerson.setSc_consigneestreet(person.getStreetAddress());
                //originalPerson.setSc_consigneeareacode(person.getAreaId());
                originalPerson.setSc_consigneepostcode(person.getZipCode());
                String taxId = getExtendFieldsValue(person.getExtendFields());
                originalPerson.setSc_consigneetaxid(taxId);
                originalPerson.setSc_consigneevatno(taxId);
            }
            return originalPerson;
        }
        return originalPerson;
    }
    
    
	private static String getTelephone(ContactPerson person) {
		String telephone = null;
		if(StringUtils.isNotBlank(person.getMobile())){
			telephone = person.getMobile();
		}else{
			telephone = person.getPhone();
		}
		return telephone;
	}
	
	
	/**
	 * 获取扩展字段的值
	 * @param originalPerson
	 * @param person
	 */
	private static String getExtendFieldsValue(String extendsFields) {
		String value = null;
		if(StringUtils.isNotBlank(extendsFields)){
			String[] arr = extendsFields.split("=");
			if(arr.length > 1){
				value = arr[1];
			}
		}
		return value;
	}
	
	/**
	 * 获取扩展字段的值
	 * @param originalPerson
	 * @param person
	 */
	private static String getExtendFieldsValue(String extendsFields, String key) {
		if(StringUtils.isNotBlank(extendsFields)){
			String[] arr = extendsFields.split(";");
			for(String v : arr){
				String values[] = v.split("=");
				if(values.length == 2 && StringUtils.equalsIgnoreCase(key, values[0])){
					return values[1];
				}
			}
		}
		return null;
	}
	
	public static Map<String,ProductMapping> wrapProductMapping(List<ProductMapping> productMappings){
		Map<String,ProductMapping> localProductMappings = new HashMap<String,ProductMapping>();
		if(productMappings!=null){
			for(ProductMapping mapping : productMappings){
				localProductMappings.put(mapping.getPk_code_shipper(), mapping);
			}
		}
		return localProductMappings ;
	}
	
	public static Map<String,CountryMapping> wrapCountryMapping(List<CountryMapping> countryMappings){
		Map<String,CountryMapping> localCountryMappings = new HashMap<String,CountryMapping>();
		if(countryMappings!=null){
			for(CountryMapping country : countryMappings){
				localCountryMappings.put(country.getAect_code(), country);
			}
		}
		return localCountryMappings ;
	}
	
	public static Map<String,String> wrapMailCargoTypeMapping(List<MailCargoTypeMapping> mappings){
		Map<String,String> localMailCargoTypeMapping = new HashMap<String,String>();
		if(mappings!=null){
			for(MailCargoTypeMapping typeMapping :mappings){
				localMailCargoTypeMapping.put(typeMapping.getMct_code_shipper(), typeMapping.getMct_code());
			}
		}
		return localMailCargoTypeMapping ;
	}
	
	public static <T> boolean isEmpty(List<T> values){
		boolean result = true ;
		if(values!=null && values.size()>0){
			result = false ;
		}
		return result ;
	}
	
	public static<T> String getCacheKey(String msgType,String msgId,T event){
    	String result = "" ;
    	if(MessageConstant.XMS_AE_ORDER_MSG_TYPE_PACKAGE.equalsIgnoreCase(msgType)){
    		if(event instanceof SendEventsRequest){
    			SendEventsRequest req = (SendEventsRequest)event;
    			List<SubOrder> subOrders = req.getLogisticsEvent().getEventBody().getOrder().getSubOrders();
    			if(req.getLogisticsEvent().getEventBody().getOrder().getSubOrders().size()>0){
    				SubOrder subOrder = subOrders.get(0);
    				result = AppConstant.AE_ORDER_CACHE_KEY_PREFIX + "A."+ subOrder.getUniqueCode();
    			}
    		}   		
    	}else if(MessageConstant.XMS_AE_ORDER_MSG_TYPE_BATCH.equalsIgnoreCase(msgType)){
    		if(StringUtils.isBlank(msgId) && (event instanceof BatchSendEventsRequest)){
    			BatchSendEventsRequest req = (BatchSendEventsRequest)event;
    			msgId = req.getLogisticsEvent().getEventBody().getOrderCode();
    		}
    		if(StringUtils.isNotBlank(msgId)){
    		    result = AppConstant.AE_ORDER_CACHE_KEY_PREFIX + "B."+ msgId;
    		}
    	}else if(MessageConstant.XMS_AE_ORDER_MSG_TYPE_CANCEL.equalsIgnoreCase(msgType)){	
    		if(StringUtils.isBlank(msgId) && (event instanceof CancelEventsRequest)){
    			CancelEventsRequest req = (CancelEventsRequest)event;
    			msgId = req.getLogisticsEvent().getEventBody().getOrder().getOrderCode() ;
    		}
    		if(StringUtils.isNotBlank(msgId)){
    		    result = AppConstant.AE_ORDER_CACHE_KEY_PREFIX + "C."+ msgId;
    		}
    	}
    	return result ;
    }
}
